/*
 * Copyright (c) 2014 Strong Group - 版权所有
 * 
 * This software is the confidential and proprietary information of
 * Strong Group. You shall not disclose such confidential information 
 * and shall use it only in accordance with the terms of the license 
 * agreement you entered into with www.cnstrong.cn.
 */
package com.zuorenke.redis;

import com.zuorenke.serialize.SerializableAdapter;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;


public abstract class AbstractCacheClient implements CacheClient {
	//序列化器
	@Autowired
	private SerializableAdapter serializer;

	public void setSerializer(SerializableAdapter serializer) {
		this.serializer = serializer;
	}

	public SerializableAdapter getSerializer() {
		return serializer;
	}

	@Override
	public Boolean set(String key, Object value) {
		byte[] valueBytes = serializer.serialize(value);
		return set(key, valueBytes);
	}

	@Override
	public Boolean set(String key, int seconds, Object value) {
		byte[] valueBytes = serializer.serialize(value);
		return set(key, seconds, valueBytes);
	}
	
	@Override
	public List<Object> batchSet(List<String> keys, List<Object> values){
		List<byte[]> valueBytesList = new ArrayList<>();
		for (Object object : values) {
			byte[] valueBytes = serializer.serialize(object);
			valueBytesList.add(valueBytes);
		}
		
		return batchSets(keys, valueBytesList);
	}

	@Override
	public Object get(String key) {
		byte[] valueBytes = getBytes(key);
		return serializer.deserialize(valueBytes);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T get(String key, Class<T> t) {
		byte[] valueBytes = getBytes(key);
		return (T) serializer.deserialize(valueBytes);
	}

	@Override
	public Long lpush(String key, Object value) {
		byte[] valueBytes = serializer.serialize(value);
		return lpush(key, valueBytes);
	}

	@Override
	public List<Object> lrange(String key, int start, int end) {
		List<byte[]> list = lrangeBytes(key, start, end);
		List<Object> oList = new ArrayList<>(list.size());
		for (byte[] ba : list) {
			oList.add(serializer.deserialize(ba));
		}
		return oList;
	}

	@Override
	public Object rpop(String key) {
		byte[] bytes = rpopBytes(key);
		return serializer.deserialize(bytes);
	}

	@Override
	public Object lpop(String key) {
		byte[] bytes = lpopBytes(key);
		return serializer.deserialize(bytes);
	}

	public abstract Boolean set(String key, byte[] value);

	public abstract Boolean set(String key, int secondes, byte[] value);

	public abstract List<Object> batchSets(List<String> keys,List<byte[]> values);

	public abstract Long lpush(String key, byte[] value);

	public abstract List<byte[]> lrangeBytes(String key, int start, int end);

	public abstract byte[] rpopBytes(String key);

	public abstract byte[] lpopBytes(String key);

	public Long hset(String key, String field, Object value) {
		byte[] valueBytes = serializer.serialize(value);
		return hsetBytes(key, field, valueBytes);
	}
	
	public <T> String hmset(String key, Map<String, T> map) {
		Map<String, byte[]> mymap = new HashMap<>();
		for (Entry<String, T> entry : map.entrySet()) {
			mymap.put(entry.getKey(), serializer.serialize(entry.getValue()));
		}
		return hmsetBytes(key, mymap);
	}

	public abstract Long hsetBytes(String key, String field, byte[] value);
	
	public abstract String hmsetBytes(String key, Map<String, byte[]> map);

	public Object hget(String key, String field) {
		byte[] bytes = hgetBytes(key, field);
		return serializer.deserialize(bytes);
	}

	public List<Object> hmget(String key, String... fields) {

		List<byte[]> list = hmgetBytes(key, fields);
		List<Object> oList = new ArrayList<>(list.size());
		for (byte[] ba : list) {
			oList.add(serializer.deserialize(ba));
		}
		return oList;
	}

	public List<String> hmgetStr(String key, String... fields) {
		List<byte[]> list = hmgetBytes(key, fields);
		List<String> oList = new ArrayList<>(list.size());
		for (byte[] ba : list) {
			if (ba == null) {
				oList.add(null);
			} else {
				oList.add(new String(ba));
			}
		}
		return oList;
	}

	public abstract List<byte[]> hmgetBytes(String key, String... fields);

	public Map<String, Object> hgetAll(String key) {
		Map<byte[], byte[]> map = hgetAllBytes(key);
		Map<String, Object> omap = new HashMap<>();
		for (Entry<byte[], byte[]> entry : map.entrySet()) {
			omap.put(new String(entry.getKey()),
					serializer.deserialize(entry.getValue()));
		}
		return omap;
	}

	public abstract Map<byte[], byte[]> hgetAllBytes(String key);

}
